#install.packages("tidyverse"); install.packages("googlesheets")
rm(list = ls())
library("tidyverse")
library("plotly")
library("janitor")
source("../../funs/conv_to_points.R")
source("../../funs/trade_comp.R")
source("../../funs/adv_value_calc.R")
setwd("~/Documents/fantasy-basketball/data/nba_fantasy_data/")
bballref1920 <- read_csv("nba_fantasy_data - bballref1920.csv")
hashtag20 <- read_csv("nba_fantasy_data - 2020_hashtag_proj_clean.csv")
hashalt19 <- read_csv("nba_fantasy_data - 2019_hashtag_alt_proj.csv")
gsd2_inseason <- read_csv("Fantrax-Players-Gold Standard II.csv")
nba_schedule <- read_csv("nba_fantasy_data - 2019_nba_schedule.csv")
gsd2_contracts <- read_csv("nba_fantasy_data - gsd2_contracts_202021.csv") %>%
select(-position)
gsd2_inseason <- gsd2_inseason %>% mutate(Trade = Status)
# 2018-19 projections from hashtag
hashtag20 <- hashtag20 %>%
clean_nba_names(player) %>%
hashtag_avgs_to_fppg() %>%
select(player, contains("fppg"))
gsd2_contracts <- gsd2_contracts %>%
clean_nba_names(player)
# clean franchise data
gsd2_inseason <- gsd2_inseason %>%
rename(fntx_pts = "PTS", fntx_orb = "OREB", fntx_dreb = "DREB",
fntx_ast = "AST", fntx_stl = "ST", fntx_blk = "BLK",
fntx_tov = "TO", fntx_threes = "3PTM", fntx_fga = "FG-",
fntx_ftm = "FTM", fntx_gms = "GP", fntx_fppg = "FP/G", fpts = FPts,
trade_comp = "Trade",
nba_team = "Team", gsd2_team = "Status", player = "Player", position = "Position") %>%
mutate(nba_team = recode(nba_team, PHO = "PHX", SA = "SAS",
NY = "NYK", NO = "NOP", GS = "GSW")) %>%
clean_nba_names(player)
# join all projections
combined_data <- hashtag20 %>%
#full_join(hashtag20, by = "player") %>%
full_join(gsd2_contracts, by = "player") %>%
full_join(gsd2_inseason, by = "player") %>%
arrange(-gsd2_fppg_ht) %>%
select(player, gsd2_team, gsd2_fppg_ht, fpts, fntx_fppg, everything(),
-ld_fppg_ht, -botb_fppg_ht)
select_data <- combined_data
# Best FA available
select_data; select_data %>% filter(gsd2_team == "FA")
## # A tibble: 1,411 x 33
## player gsd2_team gsd2_fppg_ht fpts fntx_fppg fr_fppg_ht gsd2_2020 gsd2_2021
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 James… DAL 51.0 1699 54.8 57.6 30 30
## 2 Giann… MIL 48.6 2031 58.0 57.9 27.5 30.2
## 3 Luka … WSH 48.4 1725. 53.9 57.0 8.05 10.2
## 4 LeBro… MEM 44.2 1774. 49.3 53.4 30 30
## 5 Damia… LAL 43.5 1623. 47.7 48.8 30 30
## 6 Antho… NOP 43.4 1016. 44.2 50.8 30.2 30.2
## 7 Karl-… BOS 43.2 771 48.2 51.6 29.5 30
## 8 Trae … NYK 42.2 1510. 44.4 47.6 6.57 8.33
## 9 Steph… SAC 40.9 1673. 47.8 46.8 30 30
## 10 Nikol… GSW 40.4 2128. 59.1 50.4 28.5 30
## # … with 1,401 more rows, and 25 more variables: gsd2_2022 <dbl>,
## # gsd2_2023 <dbl>, gsd2_2024 <dbl>, gsd_2025 <dbl>, g_league <dbl>,
## # nba_team <chr>, position <chr>, Rk <dbl>, Age <dbl>, Opponent <lgl>, `%
## # Owned` <chr>, `+/-` <chr>, fntx_gms <dbl>, fntx_fga <dbl>,
## # fntx_threes <dbl>, fntx_ftm <dbl>, `FT-` <dbl>, fntx_pts <dbl>,
## # fntx_orb <dbl>, fntx_dreb <dbl>, fntx_ast <dbl>, fntx_stl <dbl>,
## # fntx_blk <dbl>, fntx_tov <dbl>, trade_comp <chr>
## # A tibble: 909 x 33
## player gsd2_team gsd2_fppg_ht fpts fntx_fppg fr_fppg_ht gsd2_2020 gsd2_2021
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Jabar… FA 15.9 18 9 19.6 6.5 NA
## 2 Langs… FA 15.0 181. 7.25 17.4 0.75 0.75
## 3 Wesle… FA 12.8 117. 5.86 15.4 NA NA
## 4 Deway… FA 12.4 0 0 16.1 1 NA
## 5 Ersan… FA 12.3 0 0 15.4 NA NA
## 6 Torre… FA 10.9 157 9.24 13.7 NA NA
## 7 Thon … FA 10.5 76.8 9.59 13.0 NA NA
## 8 Mike … FA 9.82 169. 9.96 12.3 NA NA
## 9 Mike … FA 9.82 0 0 12.3 NA NA
## 10 Patri… FA 9.7 7.75 2.58 12.8 NA NA
## # … with 899 more rows, and 25 more variables: gsd2_2022 <dbl>,
## # gsd2_2023 <dbl>, gsd2_2024 <dbl>, gsd_2025 <dbl>, g_league <dbl>,
## # nba_team <chr>, position <chr>, Rk <dbl>, Age <dbl>, Opponent <lgl>, `%
## # Owned` <chr>, `+/-` <chr>, fntx_gms <dbl>, fntx_fga <dbl>,
## # fntx_threes <dbl>, fntx_ftm <dbl>, `FT-` <dbl>, fntx_pts <dbl>,
## # fntx_orb <dbl>, fntx_dreb <dbl>, fntx_ast <dbl>, fntx_stl <dbl>,
## # fntx_blk <dbl>, fntx_tov <dbl>, trade_comp <chr>
Glimpse at Overall Stats
select_data %>%
#filter(player == "Skal Labissiere") %>% # by player
filter(gsd2_team == "HOU") %>%
#filter(trade_comp == "MEM") %>%
#filter(bbr_gms > 50) %>% # by games played
#filter(bbr_gsd2_fpts > 25) %>% # by 2018 stats
#filter(hta_gsd2_fpts > 25) %>% # by hta projections
#filter(ht_gsd2_fpts > 25) %>% # by ht projections
#filter(age < 25) %>% # by age
#arrange(-bbr_gsd2_fpts) %>% # arrange by 2018 stats
#arrange(-hta_gsd2_fpts) %>% # arrange by hta projections
arrange(-fntx_fppg) %>% # arrange by ht projections
select(player, fntx_fppg, gsd2_fppg_ht, #gsd2_2020, gsd2_2021, gsd2_rfa,
)
## # A tibble: 18 x 3
## player fntx_fppg gsd2_fppg_ht
## <chr> <dbl> <dbl>
## 1 Rudy Gobert 43.8 33.6
## 2 Pascal Siakam 39.4 33.2
## 3 DeMar DeRozan 38.2 31.2
## 4 LaMelo Ball 35.6 25
## 5 Kevin Huerter 24.4 17.8
## 6 Gary Trent Jr. 21.1 15.9
## 7 Garrett Temple 18.8 9.75
## 8 Grayson Allen 18.6 14.3
## 9 Pat Connaughton 17.9 12.7
## 10 Reggie Bullock 16.7 12.4
## 11 Terance Mann 12.5 2.18
## 12 Reggie Perry 10.7 NA
## 13 Jalen McDaniels 9.15 11.0
## 14 Matt Thomas 4.1 4.12
## 15 Tre Jones 2.54 NA
## 16 Nick Richards 2.5 NA
## 17 Wenyen Gabriel 2.19 5.9
## 18 Deividas Sirvydis 0.55 NA
Trade Comparison Tool
source("../../funs/trade_comp.R")
pre_trade_fntx <- pre_trade_calc(df = select_data, league = "gsd2",
current_team = gsd2_team, traded_to = trade_comp,
fppg_col = fntx_fppg, cap_col = gsd2_2020)
pre_trade_fntx; pre_trade_plot(pre_trade_fntx, var = "team_total",
league = "gsd2", plotly = FALSE)
## # A tibble: 30 x 6
## team players avg_fppg team_total cap_used cap_left
## <chr> <int> <dbl> <dbl> <dbl> <dbl>
## 1 WSH 12 27.8 890. 105. 114399895.
## 2 NYK 12 27.5 878. 93.3 114399907.
## 3 MEM 12 26.3 841. 106. 114399894.
## 4 CLE 12 25.5 815. 109. 114399891.
## 5 ATL 12 25.1 802. 102. 114399898.
## 6 CHI 12 24.9 797. 107. 114399893.
## 7 HOU 12 24.8 794. 101. 114399899.
## 8 BOS 12 24.7 792. 102. 114399898.
## 9 NOP 12 24.7 792. 101. 114399899.
## 10 PHI 12 24.7 789. 104. 114399896.
## # … with 20 more rows

post_trade_fntx <- post_trade_calc(df = select_data, league = "gsd2",
current_team = gsd2_team, traded_to = trade_comp,
fppg_col = fntx_fppg, cap_col = gsd2_2020)
post_trade_fntx; post_trade_plot(post_trade_fntx, var = "team_total",
league = "gsd2", plotly = FALSE)
## # A tibble: 30 x 6
## team players avg_fppg team_total cap_used cap_left
## <chr> <int> <dbl> <dbl> <dbl> <dbl>
## 1 WSH 12 27.8 890. 105. 114399895.
## 2 NYK 12 27.5 878. 93.3 114399907.
## 3 MEM 12 26.3 841. 106. 114399894.
## 4 CLE 12 25.5 815. 109. 114399891.
## 5 ATL 12 25.1 802. 102. 114399898.
## 6 CHI 12 24.9 797. 107. 114399893.
## 7 HOU 12 24.8 794. 101. 114399899.
## 8 BOS 12 24.7 792. 102. 114399898.
## 9 NOP 12 24.7 792. 101. 114399899.
## 10 PHI 12 24.7 789. 104. 114399896.
## # … with 20 more rows

pre_trade_fntx <- pre_trade_calc(df = select_data, league = "gsd2",
current_team = gsd2_team, traded_to = trade_comp,
fppg_col = fntx_fppg, cap_col = gsd2_2020)
pre_trade_fntx; pre_trade_plot(pre_trade_fntx, var = "avg_fppg",
league = "gsd2", plotly = FALSE)
## # A tibble: 30 x 6
## team players avg_fppg team_total cap_used cap_left
## <chr> <int> <dbl> <dbl> <dbl> <dbl>
## 1 WSH 12 27.8 890. 105. 114399895.
## 2 NYK 12 27.5 878. 93.3 114399907.
## 3 MEM 12 26.3 841. 106. 114399894.
## 4 CLE 12 25.5 815. 109. 114399891.
## 5 ATL 12 25.1 802. 102. 114399898.
## 6 CHI 12 24.9 797. 107. 114399893.
## 7 HOU 12 24.8 794. 101. 114399899.
## 8 BOS 12 24.7 792. 102. 114399898.
## 9 NOP 12 24.7 792. 101. 114399899.
## 10 PHI 12 24.7 789. 104. 114399896.
## # … with 20 more rows

post_trade_fntx <- post_trade_calc(df = select_data, league = "gsd2",
current_team = gsd2_team, traded_to = trade_comp,
fppg_col = fntx_fppg, cap_col = gsd2_2020)
post_trade_fntx; post_trade_plot(post_trade_fntx, var = "avg_fppg",
league = "gsd2", plotly = FALSE)
## # A tibble: 30 x 6
## team players avg_fppg team_total cap_used cap_left
## <chr> <int> <dbl> <dbl> <dbl> <dbl>
## 1 WSH 12 27.8 890. 105. 114399895.
## 2 NYK 12 27.5 878. 93.3 114399907.
## 3 MEM 12 26.3 841. 106. 114399894.
## 4 CLE 12 25.5 815. 109. 114399891.
## 5 ATL 12 25.1 802. 102. 114399898.
## 6 CHI 12 24.9 797. 107. 114399893.
## 7 HOU 12 24.8 794. 101. 114399899.
## 8 BOS 12 24.7 792. 102. 114399898.
## 9 NOP 12 24.7 792. 101. 114399899.
## 10 PHI 12 24.7 789. 104. 114399896.
## # … with 20 more rows

Advanced Value Calculations
Advanced Value By Player
prediction_data <- adv_value_calc(select_data,
teams = "gsd2_team",
pts = "fntx_fppg",
salaries = "gsd2_2020") %>%
rowid_to_column("rank")
prediction_data
## # A tibble: 419 x 12
## rank player teams fppg lm_pred lm_value lm_norm rf_pred rf_value rf_norm
## <int> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 Luka … WSH 53.9 20.4 33.5 3.75 40.0 13.9 2.18
## 2 2 Bam A… BKN 43.6 17.2 26.4 2.96 35.7 7.84 1.23
## 3 3 Trae … NYK 44.4 18.8 25.6 2.87 32.9 11.5 1.8
## 4 4 Shai … OKC 40.5 16.1 24.4 2.73 31.4 9.07 1.42
## 5 5 Donov… ORL 38.2 17.3 20.9 2.34 31.6 6.60 1.03
## 6 6 Jarre… GSW 36.4 15.9 20.5 2.29 25.6 10.8 1.70
## 7 7 Jayso… IND 42.4 22.4 20.0 2.24 31.2 11.2 1.76
## 8 8 Zion … LAC 42.2 22.8 19.4 2.17 34.0 8.20 1.29
## 9 9 John … SAC 34.0 16.1 17.9 2.00 31.4 2.57 0.403
## 10 10 Enes … MEM 34.7 17.1 17.6 1.97 21.1 13.6 2.13
## # … with 409 more rows, and 2 more variables: position <chr>, salaries <dbl>
# fntx residuals
ggplot(prediction_data, aes(x = salaries, y = fppg)) +
geom_smooth(method = "lm", se = FALSE, color = "black") +
geom_segment(aes(xend = salaries, yend = lm_pred), alpha = .2) +
geom_point(aes(color = abs(lm_value), size = abs(lm_value))) +
scale_color_continuous(low = "#ffcb0c", high = "#386890") +
guides(color = FALSE, size = FALSE) +
geom_point(aes(y = lm_pred), shape = 1) +
theme_minimal()

prediction_data %>% arrange(-salaries) %>%
select(rank, player, salaries, everything())
## # A tibble: 419 x 12
## rank player salaries teams fppg lm_pred lm_value lm_norm rf_pred rf_value
## <int> <chr> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 227 Antho… 30.2 NOP 44.2 44.8 -0.615 -0.069 43.1 1.10
## 2 50 James… 30 DAL 54.8 44.5 10.3 1.15 40.9 13.9
## 3 106 Kevin… 30 MIN 50.0 44.5 5.44 0.609 40.9 9.02
## 4 116 LeBro… 30 MEM 49.3 44.5 4.75 0.531 40.9 8.33
## 5 150 Steph… 30 SAC 47.8 44.5 3.27 0.366 40.9 6.85
## 6 152 Damia… 30 LAL 47.7 44.5 3.21 0.359 40.9 6.79
## 7 159 Bradl… 30 MIN 47.3 44.5 2.78 0.311 40.9 6.36
## 8 181 Russe… 30 MEM 46.2 44.5 1.68 0.188 40.9 5.26
## 9 188 Jimmy… 30 UTH 45.8 44.5 1.24 0.139 40.9 4.82
## 10 192 Kawhi… 30 ATL 45.4 44.5 0.869 0.097 40.9 4.45
## # … with 409 more rows, and 2 more variables: rf_norm <dbl>, position <chr>
prediction_data %>%
filter(fppg > 20) %>%
mutate(cost_cats = if_else(salaries < 0.5, 1, 0),
cost_cats = if_else(salaries > 5 & salaries < 10, 2, cost_cats),
cost_cats = if_else(salaries > 10 & salaries < 15, 3, cost_cats),
cost_cats = if_else(salaries > 15 & salaries < 20, 4, cost_cats),
cost_cats = if_else(salaries > 20 & salaries < 25, 5, cost_cats),
cost_cats = if_else(salaries > 25, 6, cost_cats)) %>%
group_by(cost_cats) %>%
summarize(value = sum(lm_norm)) %>%
mutate(cost_cats = recode(cost_cats,`0`="UFA",`1`="$<5M",
`2`="$5-$9.9M",`3`="$10-14.9M",
`4`="$15-19.9+M", `5`="$20-24.9+M", `6`="$25+M"))
## # A tibble: 6 x 2
## cost_cats value
## <chr> <dbl>
## 1 UFA 63.4
## 2 $5-$9.9M 43.2
## 3 $10-14.9M 5.91
## 4 $15-19.9+M 6.24
## 5 $20-24.9+M -2.64
## 6 $25+M -3.16
Advanced Value By Team
value_by_teams <- team_value_structure(input_data = prediction_data,
teams_col = teams,
value_col = lm_norm,
fppg_col = fppg)
value_by_teams
## # A tibble: 30 x 14
## teams top01 top02 top03 top04 top05 top06 top07 top08 top09 top10 top11
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 NYK 2.87 4.62 5.16 3.71 4.54 5.24 6.57 7.54 8.48 9.24 9.65
## 2 WSH 3.75 3.69 4.74 5.93 6.62 7.78 8.06 7.89 8.24 8.54 8.71
## 3 MEM 0.531 0.719 2.69 4.15 4.85 5.40 6.21 6.24 6.98 6.49 6.83
## 4 SAC 0.366 1.18 2.14 4.14 5.49 5.70 5.52 6.36 6.92 6.36 4.87
## 5 ATL 1.71 1.81 3.58 3.30 4.02 5.01 5.94 6.00 6.48 6.02 5.82
## 6 GSW 1.81 4.11 3.76 3.08 3.62 4.26 5.52 5.52 5.93 5.98 5.54
## 7 OKC 2.73 3.10 3.55 4.81 5.54 5.75 5.67 6.86 6.54 5.91 3.05
## 8 HOU 0.443 -0.128 -0.523 1.33 2.43 3.29 3.98 4.46 4.92 5.43 4.48
## 9 CLE 1.72 2.92 4.64 4.44 4.28 4.26 4.72 5.38 5.18 5.39 5.58
## 10 NOP -0.069 -0.365 1.12 2.78 3.86 4.46 3.58 4.01 4.70 5.35 5.35
## # … with 20 more rows, and 2 more variables: top12 <dbl>, top13 <dbl>
value_by_players_graph <- value_by_teams %>%
#top_n(10, top10) %>%
#filter(teams %in% c("NOP", "MIN", "DET", "UTA", "PHX", "PHI")) %>%
pivot_longer(!teams, names_to = "players", values_to = "value_extracted") %>%
ggplot(aes(x=players, y=value_extracted, group=teams)) +
geom_line(aes(color=teams))+
scale_color_manual(values=franchise_team_colors) +
theme() + theme_minimal(); ggplotly()
prediction_data %>%
filter(teams == "MEM")
## # A tibble: 17 x 12
## rank player teams fppg lm_pred lm_value lm_norm rf_pred rf_value rf_norm
## <int> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 10 Enes … MEM 34.7 17.1 17.6 1.97 21.1 13.6 2.13
## 2 31 OG An… MEM 28.9 15.8 13.1 1.46 24.5 4.43 0.695
## 3 80 Derri… MEM 22.6 15.4 7.19 0.805 20.5 2.14 0.335
## 4 88 JaVal… MEM 19.2 12.7 6.58 0.736 11.3 7.94 1.25
## 5 93 Nicol… MEM 23.4 17.2 6.24 0.699 30.2 -6.83 -1.07
## 6 111 James… MEM 23.2 18.3 4.91 0.549 18.8 4.33 0.678
## 7 116 LeBro… MEM 49.3 44.5 4.75 0.531 40.9 8.33 1.31
## 8 157 Raul … MEM 15.7 12.7 3.08 0.345 11.3 4.44 0.697
## 9 181 Russe… MEM 46.2 44.5 1.68 0.188 40.9 5.26 0.824
## 10 207 Lou W… MEM 20.7 20.4 0.339 0.038 25.6 -4.92 -0.773
## 11 234 Marki… MEM 13.4 14.3 -0.958 -0.107 13.6 -0.226 -0.037
## 12 238 Drew … MEM 11.4 12.7 -1.26 -0.141 11.3 0.105 0.015
## 13 289 Tomas… MEM 18.1 22.5 -4.42 -0.494 17.3 0.798 0.124
## 14 373 Jalen… MEM 0.38 12.1 -11.7 -1.31 9.72 -9.34 -1.47
## 15 393 Jonta… MEM 0 13.2 -13.2 -1.48 9.07 -9.07 -1.42
## 16 402 Trevo… MEM 0 13.8 -13.8 -1.54 13.8 -13.8 -2.17
## 17 407 Zhair… MEM 0 15.1 -15.1 -1.69 8.69 -8.69 -1.36
## # … with 2 more variables: position <chr>, salaries <dbl>
prediction_data %>%
select(rank, player, teams, salaries, everything()) %>%
filter(teams == "CHA")
## # A tibble: 12 x 12
## rank player teams salaries fppg lm_pred lm_value lm_norm rf_pred rf_value
## <int> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 26 Deand… CHA 10.0 36.9 22.6 14.3 1.60 29.9 6.92
## 2 33 Chris… CHA 6.5 31.3 18.7 12.6 1.40 20.3 11.0
## 3 86 Fred … CHA 19.2 39.4 32.7 6.72 0.752 34.2 5.24
## 4 109 Ty Je… CHA 2.3 19.4 14.1 5.29 0.592 18.7 0.719
## 5 174 Jayle… CHA 22.9 38.6 36.7 1.90 0.213 36.5 2.13
## 6 194 Preci… CHA 1.87 14.4 13.6 0.824 0.092 14.0 0.433
## 7 231 Svi M… CHA 1.66 12.6 13.4 -0.816 -0.091 15.4 -2.79
## 8 322 Isaac… CHA 1.66 6.95 13.4 -6.44 -0.72 15.4 -8.41
## 9 327 Damia… CHA 0.75 5.62 12.4 -6.77 -0.757 5.24 0.377
## 10 383 Grant… CHA 0.85 0 12.5 -12.5 -1.40 6.68 -6.68
## 11 397 Bogda… CHA 18 17.9 31.3 -13.4 -1.50 26.3 -8.38
## 12 401 LaMar… CHA 24 24.2 37.9 -13.8 -1.54 29.0 -4.86
## # … with 2 more variables: rf_norm <dbl>, position <chr>
bad_teams <- c("LAL", "DAL", "SAS", "PHX", "ORL",
"OKC", "TOR", "BKN", "MIL", "PHI",
"GSW", "NOP", "CHA", "SAC", "LAC", "CHI")
prediction_data %>%
filter(teams %in% bad_teams & salaries < 25 & fppg > 20) %>%
select(rank, player, teams, salaries, everything()) %>%
left_join(select_data %>% select(player, starts_with("gsd2_20")), by = "player") %>%
filter(is.na(gsd2_2021)) # expiring contracts
## # A tibble: 24 x 17
## rank player teams salaries fppg lm_pred lm_value lm_norm rf_pred rf_value
## <int> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 6 Jarre… GSW 3.91 36.4 15.9 20.5 2.29 25.6 10.8
## 2 9 John … SAC 4.14 34.0 16.1 17.9 2.00 31.4 2.57
## 3 28 Mason… NOP 7.1 32.7 19.4 13.3 1.49 24.9 7.82
## 4 36 Lauri… SAC 6.73 31 19.0 12.0 1.35 31.1 -0.131
## 5 45 Hamid… OKC 1.66 24.0 13.4 10.6 1.19 15.4 8.66
## 6 48 Josh … LAC 3.49 25.8 15.4 10.5 1.17 22.0 3.84
## 7 54 TJ Mc… CHI 3.5 25.0 15.4 9.57 1.07 18.7 6.24
## 8 58 Micha… MIL 1.5 22.4 13.2 9.14 1.02 12.5 9.82
## 9 59 Willy… CHI 1 21.7 12.7 9.04 1.01 11.3 10.4
## 10 62 Dunca… PHX 1.66 22.2 13.4 8.78 0.983 15.4 6.81
## # … with 14 more rows, and 7 more variables: rf_norm <dbl>, position <chr>,
## # gsd2_2020 <dbl>, gsd2_2021 <dbl>, gsd2_2022 <dbl>, gsd2_2023 <dbl>,
## # gsd2_2024 <dbl>